package com.zzyl.nursing.service.impl;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.huaweicloud.sdk.iotda.v5.IoTDAClient;
import com.huaweicloud.sdk.iotda.v5.model.*;
import com.zzyl.common.constant.CacheConstants;
import com.zzyl.common.exception.base.BaseException;
import com.zzyl.common.utils.DateUtils;
import com.zzyl.framework.config.IotClientConfig;
import com.zzyl.nursing.dto.DeviceDto;
import com.zzyl.nursing.utils.DateTimeZoneConverter;
import com.zzyl.nursing.vo.DeviceDataVo;
import com.zzyl.nursing.vo.DeviceDetailVo;
import com.zzyl.nursing.vo.ProductVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import com.zzyl.nursing.mapper.DeviceMapper;
import com.zzyl.nursing.domain.Device;
import com.zzyl.nursing.service.IDeviceService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import java.util.Arrays;

/**
 * 设备管理Service业务层处理
 *
 * @author zhangyan
 * @date 2025-06-01
 */
@Service
public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> implements IDeviceService {
    @Autowired
    private DeviceMapper deviceMapper;

    @Autowired
    private IoTDAClient ioTDAClient;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;


    /**
     * 查询设备管理列表
     *
     * @param device 设备管理
     * @return 设备管理
     */
    @Override
    public List<Device> selectDeviceList(Device device) {
        return deviceMapper.selectDeviceList(device);
    }

    /**
     * 同步产品列表到redis
     */
    @Override
    public void syncProductList() {
        redisTemplate.delete(CacheConstants.IOT_ALL_PRODUCT_LIST);

        //物联网平台获取
        ListProductsRequest request = new ListProductsRequest();
        request.setLimit(50);
        ListProductsResponse response = ioTDAClient.listProducts(request);
        if (response.getHttpStatusCode() != 200) {
            throw new BaseException("获取iot设备列表失败");
        }
        //存到redis
        List<ProductSummary> products = response.getProducts();
        redisTemplate.boundValueOps(CacheConstants.IOT_ALL_PRODUCT_LIST).set(JSONUtil.toJsonStr(products));

    }

    /**
     * 查询redis的产品列表
     *
     * @return
     */
    @Override
    public List<ProductVo> allProduct() {

        String str = redisTemplate.boundValueOps(CacheConstants.IOT_ALL_PRODUCT_LIST).get();
        List<ProductVo> list = new ArrayList<>();
        try {
            list = JSONUtil.toList(str, ProductVo.class);

        } catch (Exception e) {
            return List.of();
        }
        return list;
    }

    @Override
    public void registerDevice(DeviceDto deviceDto) {
        //查看设备名称在本地有没有重复
        String deviceName = deviceDto.getDeviceName();
        List<Device> deviceList = deviceMapper.selectList(new LambdaQueryWrapper<Device>().eq(Device::getDeviceName, deviceName));
        if (CollUtil.isNotEmpty(deviceList)) {
            throw new BaseException("设备名称重复");
        }

        //设备标识是否重复
        String iotId = deviceDto.getIotId();
        deviceList = deviceMapper.selectList(new LambdaQueryWrapper<Device>().eq(Device::getIotId, iotId));
        if (CollUtil.isNotEmpty(deviceList)) {
            throw new BaseException("设备标识重复");
        }

        //同一个位置是否绑定同一个设备  设备类型   具体位置  productKey
        //位置类型
        Integer locationType = deviceDto.getLocationType();
        //绑定位置
        Long bindingLocation = deviceDto.getBindingLocation();
        //产品的id
        String productKey = deviceDto.getProductKey();
        deviceList = deviceMapper.selectList(new LambdaQueryWrapper<Device>().eq(Device::getLocationType, locationType)
                .eq(Device::getBindingLocation, bindingLocation)
                .eq(Device::getProductKey, productKey));
        if (CollUtil.isNotEmpty(deviceList)) {
            throw new BaseException("同一个位置绑定");
        }

        //iot注册设备
        AddDeviceRequest request = new AddDeviceRequest();
        AddDevice addDevice = new AddDevice();
        addDevice.setNodeId(deviceDto.getNodeId());
        addDevice.setDeviceName(deviceName);
        addDevice.setProductId(productKey);
        AuthInfo authInfo = new AuthInfo(); //秘钥
        String secret = RandomUtil.randomString(32);
        authInfo.setSecret(secret);
        addDevice.setAuthInfo(authInfo);
        addDevice.setDescription(deviceDto.getDeviceDescription());

        request.setBody(addDevice);
        AddDeviceResponse response = ioTDAClient.addDevice(request);

        if (response.getHttpStatusCode() != 201) {
            throw new BaseException("设备添加失败");
        }
        String deviceId = response.getDeviceId();

        //本地保存设备
        Device device = BeanUtil.toBean(deviceDto, Device.class);
        device.setIotId(deviceId);
        device.setSecret(secret);

        save(device);
    }

    @Override
    public DeviceDetailVo deviceDetail(String iotId) {
        //查询本地库信息
        if (StrUtil.isEmpty(iotId)) {
            throw new BaseException("参数异常");
        }
        Device device = deviceMapper.selectOne(new LambdaQueryWrapper<Device>().eq(Device::getIotId, iotId));
        DeviceDetailVo deviceDetailVo = BeanUtil.toBean(device, DeviceDetailVo.class);

        //查询华为云iot
        ShowDeviceRequest request = new ShowDeviceRequest();
        request.setDeviceId(iotId);
        ShowDeviceResponse response = ioTDAClient.showDevice(request);
        if (response.getHttpStatusCode() != 200) {
            throw new BaseException("查询设备信息失败");
        }


        String status = response.getStatus();
        String activeTime = response.getActiveTime();
        if (StrUtil.isNotEmpty(activeTime)){
            LocalDateTime parse = LocalDateTimeUtil.parse(activeTime, DatePattern.UTC_MS_PATTERN);
            LocalDateTime localDateTime = DateTimeZoneConverter.utcToShanghai(parse);
            deviceDetailVo.setActiveTime(localDateTime);
        }
        deviceDetailVo.setDeviceStatus(status);


        return deviceDetailVo;
    }

    @Override
    public List<DeviceDataVo> queryServiceProperties(String iotId) {
        List<DeviceDataVo> list = new ArrayList<>();

        ShowDeviceShadowRequest request = new ShowDeviceShadowRequest();
        request.setDeviceId(iotId);
        ShowDeviceShadowResponse response = ioTDAClient.showDeviceShadow(request);

        if (response.getHttpStatusCode() != 200) {
            throw new BaseException("查询设备影子数据失败");
        }
        List<DeviceShadowData> shadow = response.getShadow();
        DeviceShadowProperties reported = shadow.get(0).getReported();
        String eventTimeStr = reported.getEventTime();
        LocalDateTime eventTime = LocalDateTime.now();
        if (StrUtil.isNotEmpty(eventTimeStr)){
            LocalDateTime eventTimeUTC = LocalDateTimeUtil.parse(eventTimeStr, "yyyyMMdd'T'HHmmss'Z'");
            eventTime = DateTimeZoneConverter.utcToShanghai(eventTimeUTC);
        }
        Object properties = reported.getProperties();
        JSONObject jsonObject = JSONUtil.parseObj(properties);
        LocalDateTime finalEventTime = eventTime;
        jsonObject.forEach((key, value) -> {
            list.add(new DeviceDataVo(key, finalEventTime, value));
        });

        return list;
    }

    @Override
    public void updateDevice(DeviceDto deviceDto) {
        //参数校验
        if (deviceDto == null) {
            throw new BaseException("参数异常");
        }

        String productKey = deviceDto.getProductKey();
        Integer locationType = deviceDto.getLocationType();
        Long bindingLocation = deviceDto.getBindingLocation();

        //校验同一产品的设备无法绑定同一位置
        List<Device> deviceList = deviceMapper.selectList(new LambdaQueryWrapper<Device>().eq(Device::getLocationType, locationType)
                .eq(Device::getBindingLocation, bindingLocation)
                .eq(Device::getProductKey, productKey));
        if (CollUtil.isNotEmpty(deviceList)) {
            throw new BaseException("同一个位置绑定");
        }

        //修改平台
        UpdateDeviceRequest request = new UpdateDeviceRequest();
        request.setDeviceId(deviceDto.getIotId());
        UpdateDevice body = new UpdateDevice();
        body.setDeviceName(deviceDto.getDeviceName());
        body.setDescription(deviceDto.getDeviceDescription());
        request.setBody(body);
        UpdateDeviceResponse response = ioTDAClient.updateDevice(request);
        if (response.getHttpStatusCode() != 200) {
            throw new BaseException("修改失败");
        }

        //修改本地
        Device device = BeanUtil.toBean(deviceDto, Device.class);
        deviceMapper.updateById(device);
    }

    @Override
    public void deleteDevice(String iotId) {
        //校验参数
        if (StrUtil.isEmpty(iotId)){
            throw new BaseException("参数异常");
        }
        LambdaQueryWrapper<Device> eq = new LambdaQueryWrapper<Device>().eq(Device::getIotId, iotId);
        //查询本地是否存在
        long count = this.count(eq);
        if (count == 0){
            throw new BaseException("删除设备不存在");
        }

        //删除平台
        DeleteDeviceRequest request = new DeleteDeviceRequest();
        request.setDeviceId(iotId);
        DeleteDeviceResponse response = ioTDAClient.deleteDevice(request);

        if (response.getHttpStatusCode() != 204){
            throw new BaseException("华为iot平台删除失败");
        }

        int delete = deviceMapper.delete(eq);
        if (delete == 0){
            throw new BaseException("本地数据库删除失败");
        }
    }


}
